﻿using System.Text.RegularExpressions;
using NetEasyMusic.Lib.Details;
using NetEasyMusic.Lib.Models;

// ReSharper disable StringLiteralTypo
// ReSharper disable MemberCanBePrivate.Global
namespace NetEasyMusic.Lib.Data;

public class Music : DataBasic
{
    public Music(string cookie) : base(cookie)
    {
    }

    public Music(string url, bool isUse = false) : base(url, isUse)
    {
    }

    public Music()
    {
    }

    public static Dictionary<string, string> Level => new()
    {
        { "标准", "standard" },
        { "较高", "higher" },
        { "极高", "exhigh" },
        { "无损", "lossless" },
        { "Hi - Res", "hires" },
        { "高清环绕声", "jyeffect" },
        { "沉浸环绕声", "sky" },
        { "超清母带", "jymaster" }
    };

    /// <summary>
    /// 获取歌曲详情信息
    /// </summary>
    /// <param name="model">歌曲的Model</param>
    /// <returns>歌曲详情信息</returns>
    public async Task<SongDetailModel> GetSong(SongModel model)
    {
        var l = await FindLyric(model.Id);
        var c = await GetCommend(model.Id);
        return new SongDetailModel
        {
            Lyric = l,
            Comments = c,
            Name = model.Name,
            Album = model.Album,
            PicUrl = model.PicUrl
        };
    }


    /// <summary>
    /// 获取没有评论的歌曲详情信息
    /// </summary>
    /// <param name="model">歌曲的Model</param>
    /// <returns>没有评论的歌曲详情信息</returns>
    public async Task<SongDetailModel> GetSongWithoutCommend(SongModel model)
        => new()
        {
            Lyric = await FindLyric(model.Id),
            Name = model.Name,
            Album = model.Album,
            PicUrl = model.PicUrl
        };


    /// <summary>
    /// 从id得到歌曲信息
    /// </summary>
    /// <param name="id">歌曲id</param>
    /// <returns>歌曲信息</returns>
    public async Task<SongModel> GetSongFormId(string id)
    {
        var obj = await GetFormString($"/song/detail?ids={id}");
        if (obj == null) return new SongModel();
        var context = obj["songs"]?[0]!;
        return new SongModel()
        {
            Name = context["name"]?.ToObject<string>()!,
            Id = id,
            PicUrl = context["al"]?["picUrl"]?.ToObject<string>()!,
            Time = context["dt"]!.ToObject<string>()!,
        };
    }


    /// <summary>
    /// 从歌曲ID得到歌词
    /// </summary>
    /// <param name="id">歌曲ID</param>
    /// <returns>歌词</returns>
    public async Task<string> FindLyric(string id)
    {
        var obj = await GetFormString($"/lyric?id={id}");
        if (obj == null) return "";
        return obj["lrc"]!["lyric"] + obj["tlyric"]?["lyric"]?.ToString();
    }

    /// <summary>
    /// 从歌曲ID得到评论
    /// </summary>
    /// <param name="id">歌曲ID</param>
    /// <returns></returns>
    public async Task<Comments> GetCommend(string id)
    {
        var context = await GetFormString($"/comment/music?id={id}");
        if (context == null) return new Comments();
        var comments = new Comments
        {
            Total = context["total"]!.ToObject<string>()!,
            HotComment = context["hotComments"]!.Select(x => new Comment
            {
                Time = x["timeStr"]!.ToObject<string>()!,
                Context = x["content"]!.ToObject<string>()!,
                User = new UserModel
                {
                    AvatarUrl = x["user"]!["avatarUrl"]!.ToObject<string>()!,
                    Nickname = x["user"]!["nickname"]!.ToObject<string>()!,
                    UserId = x["user"]!["userId"]!.ToObject<string>()!
                }
            }).ToArray(),
            OtherComment = context["comments"]!.Select(x => new Comment
            {
                Time = x["timeStr"]!.ToObject<string>()!,
                Context = x["content"]!.ToObject<string>()!,
                User = new UserModel
                {
                    AvatarUrl = x["user"]!["avatarUrl"]!.ToObject<string>()!,
                    Nickname = x["user"]!["nickname"]!.ToObject<string>()!,
                    UserId = x["user"]!["userId"]!.ToObject<string>()!
                }
            }).ToArray()
        };
        return comments;
    }


    /// <summary>
    /// 获取歌曲URL
    /// </summary>
    /// <param name="id">歌曲ID</param>
    /// <param name="level">等级</param>
    /// <returns>歌曲URL</returns>
    public async Task<string> GetUrl(string id, string level = "standard")
    {
        var context = await GetFormString($"/song/url/v1?id={id}&level={level}&cookie={Cookie}");
        return context?["data"]![0]!["url"]!.ToObject<string>()!;
    }

    /// <summary>
    /// 将歌词解析成字典
    /// </summary>
    /// <param name="context">歌词内容</param>
    /// <returns>字典</returns>
    public static Dictionary<double, string> InitLrc(string context)
    {
        var dicWord = new Dictionary<double, string>();
        foreach (var line in context.Split("\n"))
        {
            var regexWord = new Regex(@".*\](.*)");
            var mcw = regexWord.Match(line);
            if (mcw.Groups.Count < 2) continue;
            var word = mcw.Groups[1].Value;
            var regexTime = new Regex(@"\[([0-9.:]*)\]", RegexOptions.Compiled);
            var mct = regexTime.Matches(line);
            foreach (Match item in mct)
            {
                if (item.Groups.Count < 2) continue;
                var time = TimeSpan.Parse("00:" + item.Groups[1].Value).TotalSeconds;
                if (!dicWord.TryAdd(time, word)) dicWord[time] += $"\n{word}";
            }
        }

        return dicWord;
    }
}